package com.hc.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.hc.common.bean.Result;
import com.hc.common.bean.ResultUtil;
import com.hc.common.service.RedisService;
import com.hc.common.utils.JsonUtil;
import com.hc.constant.RedisConst;
import com.hc.constant.UserConst;
import com.hc.domain.User;
import com.hc.res.MenuItemAuth;
import com.hc.security.jwt.JwtUtil;
import com.hc.service.UserService;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.io.Serializable;

/**
 * @author hecai
 * @date 2021/12/20 17:59
 */
@RestController
@RequestMapping("/user")
public class UserController {

    @Resource
    private UserService userService;

    @PostMapping
    public Result create(@RequestBody User user) {
        boolean res = userService.save(user);
        return res ? ResultUtil.success("添加成功") : ResultUtil.fail("添加失败");
    }

    @PutMapping
    public Result updateById(@RequestBody User user) {
        boolean res = userService.updateById(user);
        return res ? ResultUtil.success("更新成功") : ResultUtil.fail("更新失败");
    }

    @DeleteMapping("{id}")
    public Result removeById(@PathVariable Serializable id) {
        boolean res = userService.removeById(id);
        return res ? ResultUtil.success("删除成功") : ResultUtil.fail("删除失败");
    }

    @GetMapping("{id}")
    public Result getById(@PathVariable Serializable id) {
        User res = userService.getById(id);
        return ResultUtil.success("查询成功").setData(res);
    }

    //@PostMapping
    //public Result getByCondition(@RequestBody UserQuery condition) {
    //    List<User> list = userService.queryByCondition(condition);
    //    return ResultUtil.success("查询成功").setData(list);
    //}

    @Resource
    private JwtUtil jwtUtil;

    @Resource
    private RedisService<User> userRedisService;

    @Resource
    private AuthenticationManager authenticationManager;

    @PostMapping("/login0")
    public Result login0(@RequestParam String username, @RequestParam String password){
        System.out.println(username+" "+password);
        return ResultUtil.success();
    }

    @PostMapping("/login")
    public Result login(@RequestBody User user) {
        // 登陆验证
        UsernamePasswordAuthenticationToken token0 =
                new UsernamePasswordAuthenticationToken(user.getUsername(), user.getPassword());
        Authentication authentication = authenticationManager.authenticate(token0);
        SecurityContextHolder.getContext().setAuthentication(authentication);

        User user1 = userService.getOne(new QueryWrapper<User>()
                .eq("username", user.getUsername())
                .eq("status", UserConst.Status.ok));

        //将缓存中的用户删除（不管这个用户之前是否缓存）
        userRedisService.zsetRemove(RedisConst.User, user1);
        //每次登录，priority+1---登录成功之后，将数据库中用户的priority+1
        user1.setPriority(user1.getPriority() + 1);
        userService.updateById(user1);
        //将新登录用户缓存到Redis中
        userRedisService.zsetAdd(RedisConst.User, user1, Double.valueOf(user1.getPriority()));
        //将Redis中最小的删除
        if (userRedisService.zsetSize(RedisConst.User) > RedisConst.CACHED_ACTIVE_USER_AMOUNT) {
            userRedisService.zsetPopMin(RedisConst.User);
        }

        //生成token，返回给客户端
        MenuItemAuth menuItemAuth = userService.getAuthoritiesPermissions(user.getUsername());
        System.out.println(JsonUtil.obj2String(menuItemAuth));
        UserDetails userDetails = org.springframework.security.core.userdetails.User.withUsername(user.getUsername())
                .password(menuItemAuth.getPassword())
                .authorities(menuItemAuth.getAuth().split(","))
                .build();

        String token = jwtUtil.generateToken(userDetails, user1.getId() + "");

        return ResultUtil.success().setData("token", token);
    }

    @PostMapping("/getMenu")
    public Result getMenu(@RequestHeader("Authorization") String token) {
        String username = jwtUtil.getSubjectFromToken(token);
        //生成token，返回给客户端
        MenuItemAuth menuItemAuth = userService.getAuthoritiesPermissions(username);

        return ResultUtil.success().setData("menuList", menuItemAuth.getMenuItemList());
    }
}
